﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using HtmlAgilityPack;

class Program
{
    static readonly HttpClient client = new HttpClient();
    static SemaphoreSlim semaphore = new SemaphoreSlim(5); // 最大并发控制
    static ConcurrentDictionary<string, List<string>> phoneDict = new ConcurrentDictionary<string, List<string>>();
    static ConcurrentBag<string> visitedUrls = new ConcurrentBag<string>();
    static Regex phoneRegex = new Regex(@"\b0\d{2,3}-\d{7,8}\b", RegexOptions.Compiled);

    static async Task Main()
    {
        // 设置 User-Agent 伪装浏览器
        client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

        Console.Write("请输入搜索关键词：");
        string keyword = Console.ReadLine()?.Trim();
        if (string.IsNullOrEmpty(keyword))
        {
            Console.WriteLine("关键词不能为空！");
            return;
        }

        try
        {
            var searchUrls = await GetSearchUrlsAsync(keyword);

            if (searchUrls.Count == 0)
            {
                Console.WriteLine("未找到任何搜索结果。");
                return;
            }

            var tasks = new List<Task>();
            foreach (var url in searchUrls)
            {
                tasks.Add(ProcessUrlAsync(url));
            }

            await Task.WhenAll(tasks);

            Console.WriteLine("\n已爬取URL列表：");
            foreach (var url in visitedUrls)
            {
                Console.WriteLine(url);
            }

            Console.WriteLine($"\n高校电话号码（共 {phoneDict.Count} 个）:");
            foreach (var kvp in phoneDict)
            {
                Console.WriteLine($"{kvp.Key} 来自以下网址：");
                foreach (var u in kvp.Value)
                {
                    Console.WriteLine($"  - {u}");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("运行时出错: " + ex.Message);
        }
    }

    static async Task<List<string>> GetSearchUrlsAsync(string keyword)
    {
        var links = new List<string>();
        try
        {
            string searchUrl = $"https://www.bing.com/search?q={Uri.EscapeDataString(keyword + " 高校 联系方式")}";
            string html = await client.GetStringAsync(searchUrl);

            var doc = new HtmlDocument();
            doc.LoadHtml(html);
            var nodes = doc.DocumentNode.SelectNodes("//li[@class='b_algo']//h2/a");

            if (nodes != null)
            {
                foreach (var node in nodes)
                {
                    var href = node.GetAttributeValue("href", "");
                    if (!string.IsNullOrEmpty(href) && (href.StartsWith("http") || href.StartsWith("https")))
                    {
                        links.Add(href);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("获取搜索结果失败：" + ex.Message);
        }

        return links;
    }

    static async Task ProcessUrlAsync(string url)
    {
        if (phoneDict.Count >= 50) return;

        await semaphore.WaitAsync();
        try
        {
            string html = await client.GetStringAsync(url);
            visitedUrls.Add(url);

            foreach (Match match in phoneRegex.Matches(html))
            {
                string phone = match.Value;
                phoneDict.AddOrUpdate(phone,
                    new List<string> { url },
                    (key, list) =>
                    {
                        if (!list.Contains(url)) list.Add(url);
                        return list;
                    });

                if (phoneDict.Count >= 50) break;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"抓取 {url} 时出错: {ex.Message}");
        }
        finally
        {
            semaphore.Release();
        }
    }
}
